require 'open_pinduoduo/version'
require 'rest-client'
require 'digest'
require 'yaml'
require 'open_pinduoduo/railtie' if defined? Rails

module OpenPinduoduo

  API_VERSION = 'V1'
  DATA_TYPE = 'JSON'

  class Error < StandardError; end

  # Your code goes here...

  class << self
    attr_accessor :config

    def load(config_file)
      @config = YAML.load_file(config_file)
      @config = config[Rails.env] if defined? Rails
      check_config_and_export_to_env
    end

    def check_config_and_export_to_env
      check_config
      export_to_env
    end

    def check_config
      list = []
      %w[client_id client_secret endpoint].map do |k|
        list << k unless config.key?(k)
      end

      raise "[#{list.join(', ')}] not included in your yaml file." unless list.empty?
    end

    def export_to_env
      ENV['PDD_API_KEY'] = config['client_id']
      ENV['PDD_SECRET_KEY'] = config['client_secret']
      ENV['PDD_ENDPOINT'] = config['endpoint']
    end

    def sign(params)
      Digest::MD5.hexdigest(wrap_with_secret sorted_options_string(params)).upcase
    end

    def wrap_with_secret(s)
      "#{config['secret_key']}#{s}#{config['secret_secret']}"
    end

    def sorted_options_string(options)
      options.sort.map(&:join).join
    end

    def full_options(params)
      {
        timestamp: Time.current.to_i,
        client_id: config['client_id'],
        data_type: DATA_TYPE,
        version: API_VERSION
      }.merge(params)
    end

    def query_hash(params)
      params = full_options(params)
      params[:sign] = sign(params)
      params
    end

    def query_string(params)
      '?' + query_hash(params).to_query
    end

    def url(params)
      '%s%s' % [config['endpoint'], query_string(params)]
    end

    def parse_result(data)
      JSON.parse(data)
    end

    def get(params)
      path = query_hash(params)
      parse_result(RestClient::Request.execute(method: :get, url: "#{config['endpoint']}#{path}"))
    end

    def get!(params)
      response = get(params)
      raise Error, response['error_message'].to_json if response.key?('error_response')
      response
    end

    def post(params)
      parse_result(RestClient::Request.execute(method: :post, url: config['endpoint'], payload: query_hash(params)))
    end

    def post!(params)
      response = post(params)
      raise Error, response['error_message'].to_json if response.key?('error_response')
      response
    end
  end
end
